package com.mentaleye.controller;

import com.mentaleye.bean.CommonResult;
import com.mentaleye.bean.PayBackBean;
import com.mentaleye.bean.PayBean;
import com.mentaleye.dal.model.TradesRecord;
import com.mentaleye.dal.model.TrxRecord;
import com.mentaleye.enumpackage.AliTradeStatusEnum;
import com.mentaleye.enumpackage.OrderStatusEnum;
import com.mentaleye.enumpackage.TradeStatusEnum;
import com.mentaleye.enumpackage.TradeTypeEnum;
import com.mentaleye.redis.lock.RedisBasedDistributedLock;
import com.mentaleye.service.OrderService;
import com.mentaleye.service.PayService;
import com.mentaleye.service.impl.PayServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Skeyedu on 2017/6/14.
 */
@Controller
@RequestMapping({"/pay"})
public class PayController {
    private static Logger logger = LoggerFactory.getLogger(PayServiceImpl.class);
    @Autowired
    OrderService orderService;

    @Autowired
    PayService payService;

    @RequestMapping("/goToPay")
    @ResponseBody
    public CommonResult goToPay(@RequestBody PayBean payBean) {
        CommonResult commonResult = new CommonResult();
        RedisBasedDistributedLock redisBasedDistributedLock = null;
        boolean needUnlock=false;
        try {
            //并发锁 确定 5分钟内 只有一次 处理请求
            redisBasedDistributedLock = new RedisBasedDistributedLock("goToPay" + payBean.getOutTradeNo(), 120000);
            if (!redisBasedDistributedLock.tryLock()) {
                commonResult.setResultMsg(payBean.getOutTradeNo() + "交易重复，请稍后重试");
                return commonResult;
            }
            needUnlock=true;
            TradesRecord tradesRecord = orderService.getByOrderNo(payBean.getOrderNo());
            //订单找不到
            if (tradesRecord == null) {
                commonResult.setResultMsg(payBean.getOutTradeNo() + "找不到订单号");
                return commonResult;
            }
            //判断订单状态是否是未支付 不是未支付 直接返回提示 支付状态不正确
            if (!OrderStatusEnum.WAITING_PAYMENT.name().equalsIgnoreCase(tradesRecord.getTrxStatus())) {
                commonResult.setResultMsg(payBean.getOutTradeNo() + "订单状态不正确为:" + tradesRecord.getTrxStatus());
                return commonResult;
            }

            //判断订单金额是否和支付的一致
            if (tradesRecord.getOrderAmount().doubleValue()!=Double.parseDouble(payBean.getTotalAmount())) {
                commonResult.setResultMsg(payBean.getOutTradeNo() + "订单金额不正确");
                return commonResult;
            }

            //判断该订单类型是否有该交易类型该订单号在处理中的流水
            List<TrxRecord> trxRecords = orderService.getTRXByOrderNo(payBean.getOrderNo(), TradeTypeEnum.PAY.name(), TradeStatusEnum.WAITING.name());
            if (trxRecords != null && trxRecords.size() > 0) {
                boolean hasPaySuccess = false;//是否支付成功
                TrxRecord trxRecordSuccess = null;//支付成功的流水
                TrxRecord trxRecordWait = null;//支付等待的流水
                List<String> failTrxRecordNos = new ArrayList<String>();//支付失败的流水
                //在处理中的查询 支付宝支付状态 状态成功支付成功就返回支付成功(修改支付流水状态) 支付失败(原支付流水状态失败)
                CommonResult queryStatus;
                for (TrxRecord trxRecord : trxRecords) {
                    queryStatus = payService.tradeQuery(trxRecord.getTrxNo());
                    if (queryStatus.getIsSuccess()) {
                        if (AliTradeStatusEnum.TRADE_SUCCESS.equals(queryStatus.getData()) || AliTradeStatusEnum.TRADE_FINISHED.equals(queryStatus.getData())) {
                            hasPaySuccess = true;
                            trxRecordSuccess = trxRecord;
                        } else if (AliTradeStatusEnum.TRADE_CLOSED.equals(queryStatus.getData())||AliTradeStatusEnum.NO_EXSIT.equals(queryStatus.getData())) {
                            failTrxRecordNos.add(trxRecord.getTrxNo());
                        } else if (AliTradeStatusEnum.WAIT_BUYER_PAY.equals(queryStatus.getData())) {
                            trxRecordWait = trxRecord;
                        }
                    }else{
                        commonResult.setResultMsg( "蚂蚁金服调用接口异常");
                        return commonResult;
                    }

                }
                if (failTrxRecordNos.size() > 0) {
                    orderService.failTRX(failTrxRecordNos);//失败的流水修改成失败状态
                }
                if (hasPaySuccess) {
                    payBack(trxRecordSuccess.getTrxNo(), AliTradeStatusEnum.TRADE_SUCCESS.name());//直接处理订单为支付成功
                    commonResult.setResultMsg(payBean.getOutTradeNo() + "订单已经支付了");
                    return commonResult;
                }
                if (trxRecordWait != null) {
                    commonResult.setResultMsg(payBean.getOutTradeNo() + "订单支付正在处理中");
                    return commonResult;
                }

            }

            TrxRecord record = new TrxRecord(payBean);
            orderService.insertTrxRecord(record);//初始化流水记录
            CommonResult getPayResult = payService.getPayPage(payBean);//获取支付页面
            if (getPayResult.getIsSuccess()) {
                record.setTrxStatus(TradeStatusEnum.WAITING.name());
                orderService.updateTrxRecord(record);//修改 流水状态为处理中
                return getPayResult;
            }


        } catch (Exception e) {
            logger.error("获取支付页面异常", e);
        } finally {
            if (needUnlock&&redisBasedDistributedLock != null)
                redisBasedDistributedLock.unlock();//解除锁定
        }
        return commonResult;
    }


    private CommonResult payBack(String outTradeNo, String tradeStatus) {
        CommonResult commonResult = new CommonResult();

        //根据流水号查询订单
        TradesRecord tradesRecord = orderService.getByTransNo(outTradeNo);
        //订单找不到
        if (tradesRecord == null) {
            commonResult.setResultMsg(outTradeNo + "流水号找不到对应订单号");
            return commonResult;
        }
        // 判断订单状态是否是支付成功了 直接返回提示 支付成功
        if(OrderStatusEnum.SUCCESS.name().equals(tradesRecord.getTrxStatus())){
            commonResult.setIsSuccess(true);
            commonResult.setResultMsg("订单已经支付");
            return commonResult;
        }
        if(!OrderStatusEnum.WAITING_PAYMENT.name().equals(tradesRecord.getTrxStatus())){
            commonResult.setResultMsg("订单状态不正确");
            return commonResult;
        }
        //获取流水号 是否能查询到对应的流水数据 流水的状态是否是处理中
        TrxRecord record =orderService.getByTrxNo(outTradeNo);
        if(record==null){
            commonResult.setResultMsg("订单流水不存在");
            return commonResult;
        }
        if(!TradeStatusEnum.WAITING.name().equals(record.getTrxStatus())){
            commonResult.setResultMsg("订单流水状态不正确");
            return commonResult;
        }

        if (AliTradeStatusEnum.TRADE_SUCCESS.name().equals(tradeStatus) || AliTradeStatusEnum.TRADE_FINISHED.name().equals(tradeStatus)) {
            record.setTrxStatus(TradeStatusEnum.SUCCESS.name());
            orderService.updateTrxRecord(record);//修改 流水状态为支付成功
            tradesRecord.setTrxStatus(OrderStatusEnum.SUCCESS.name());//订单支付成功
            tradesRecord.setTrxNo(outTradeNo);
            orderService.updateOrder(tradesRecord);
            commonResult.setIsSuccess(true);
        }

        return commonResult;

    }

    @RequestMapping("/payBack")
    @ResponseBody
    public CommonResult payBack(@RequestBody PayBackBean payBackBean) {
        //并发锁 确定 5分钟内 只有一次 处理请求
        CommonResult commonResult = new CommonResult();
        RedisBasedDistributedLock redisBasedDistributedLock = null;
        boolean needUnlock=false;
        try {

            //支付宝交易号
            String outTradeNo = payBackBean.getParams().get("out_trade_no");
            //交易状态
            String tradeStatus = payBackBean.getParams().get("trade_status");
            //并发锁 确定 5分钟内 只有一次 处理请求
            redisBasedDistributedLock = new RedisBasedDistributedLock("payBack" + outTradeNo, 120000);
            if (!redisBasedDistributedLock.tryLock()) {
                commonResult.setResultMsg(outTradeNo + "交易重复，请稍后重试");
                return commonResult;
            }

            commonResult= payBack(outTradeNo,tradeStatus);



        } catch (Exception e) {
            logger.error("获取支付页面异常", e);
        }finally {
            if (needUnlock&&redisBasedDistributedLock != null)
                redisBasedDistributedLock.unlock();//解除锁定
        }


        return commonResult;
    }

    @RequestMapping("/toPay")
    public String toPay() {
        return "pay/toPay";
    }
}
